package com.wnxy.controller;


import com.google.code.kaptcha.Producer;
import com.wnxy.entity.User;
import com.wnxy.service.UserService;
import com.wnxy.utils.Md5Util;
import com.wnxy.utils.UserTokenUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author 林夕
 * @since 2023-03-11 04:45:21
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    Producer producer;
    @Autowired
    UserService userService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /* 验证码的发送 */
    @RequestMapping("getEmailCode")
    public String getEmailCode(String email){
        //正则表达式判断邮箱地址是否正确 (此处为QQ邮箱验证)
        String format = "[1-9]\\d{7,10}@qq\\.com";

        if (email==null || !email.matches(format)){
            return "邮箱地址为空邮箱地址非法,请重新输入!";
        }

        Random random = new Random();
        //发送邮箱验证码 (设置动态即生成一个随机数)
        String code = String.valueOf(random.nextInt(9000) + 1000);

        //发送邮件
        /* 方案一 多线程 */
        /*
            new Thread(new Runnable() {
                @Override
                public void run() {
                    sendEmail(email,"您的蜗牛军火库注册验证码","您的验证码为 "+code+" ,有效期为5分钟,请尽快使用");
                }
            }).start();
        */

        /* 方案二  使用MQ */
        Map<String,String> map = new HashMap<>();
        map.put("email",email);
        map.put("subject","您的蜗牛军火库注册验证码");
        map.put("text","您的验证码为  " +  code + ",有效期为5分钟,请尽快使用");
        rabbitTemplate.convertAndSend("sendEmailExchange","sendEmail",map);


        //保存到redis中,有效期5分钟
        stringRedisTemplate.opsForValue().set(email,code,5, TimeUnit.MINUTES);

        return "ok";
    }

    /* 注册 */
    @RequestMapping("register")
    public String register(User user,String repass, String emailCode){

        /* 用姓名做同步锁  为了保险期间,从字符串常量池中获取字符串对象 (防止同一时间同一用户注册) */
        synchronized (user.getUsername().intern()) {
        /*
            用户名需要保证唯一性
            方案1: 数据库里设置username列唯一索引
            方案2: 程序里先检查该用户是否存在,如果已经已经就拒绝注册
        */
            // 用户名为空
            if (StringUtils.isEmpty(user.getUsername())) {
                return "用户名为空,请输入用户名";
            }
            User userByName = userService.getUserByName(user.getUsername());
            // 用户名已存在
            if (userByName != null) {
                return "用户名已存在,请重新输入";
            }

            /* 校验密码 */
            if (StringUtils.isEmpty(user.getPassword()) || StringUtils.isEmpty(repass) || !user.getPassword().equals(repass)) {
                return "密码为空或两次输入密码不一致,请检查后重新输入";
            }

            /* 校验邮箱验证码 */
            if (StringUtils.isEmpty(user.getEmail()) || StringUtils.isEmpty(emailCode) || !emailCode.equalsIgnoreCase(stringRedisTemplate.opsForValue().get(user.getEmail()))) {
                return "邮箱地址或邮箱验证码错误";
            }

            /* 注册用户 并在注册前对密码进行加密处理 */
            user.setPassword(Md5Util.encode(user.getPassword()));
            userService.save(user);
            // 注册成功发送欢迎邮件
            /* 方案一 使用多线程 */
            /*
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        sendEmail(user.getEmail(),"欢迎注册蜗牛军火库","祝您购物愉快");
                    }
                }).start();
            */

            /* 方案二  使用 MQ */
            Map<String,String> map = new HashMap<>();
            map.put("email",user.getEmail());
            map.put("subject","欢迎注册蜗牛军火库");
            map.put("text","祝您购物愉快");
            rabbitTemplate.convertAndSend("sendEmailExchange","sendEmail",map);

            return "ok";
        }
    }

    /* 提取发送邮件的方法
        private void sendEmail(String toEmail,String subject, String text){
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom("478588968@qq.com");
            message.setTo(toEmail);
            message.setSubject(subject);
            message.setText(text);

            javaMailSender.send(message);
        }
    */

    /* 登录页面验证码图片生成 */
    @RequestMapping("verifyCode")
    public void verifyCode(HttpServletResponse response, HttpSession session) throws IOException {
        /* 1.生成验证码字符串 */
        String verifyCode  = producer.createText();
        //将验证码保存在session中
        session.setAttribute("verifyCode",verifyCode);

        /* 2.字符串转为图片 */
        BufferedImage image = producer.createImage(verifyCode);

        response.setContentType("image/jpeg");
        ImageIO.write(image,"jpg",response.getOutputStream());
    }

    /* 登录 */
    @RequestMapping("login")
    public String login(String username, String password, String code, HttpSession session, HttpServletResponse response){
        //检验用户是否存在
        User user = userService.getUserByName(username);
        if (user == null){
            return "用户名或密码错误!";
        }else if (!user.getPassword().equalsIgnoreCase(Md5Util.encode(password))){
            return "用户名或密码错误!";
        }

        //检验验证码
        String newVerifyCode = (String) session.getAttribute("verifyCode");
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(newVerifyCode) || !code.equalsIgnoreCase(newVerifyCode)){
            return "验证码为空 或 验证码错误,请检查后重新输入";
        }
        //将登录的用户信息(页面要显示的用户名)保存在token中
        UserTokenUtil.createUserToken(user.getUsername(),response,stringRedisTemplate);

        return "ok";
    }

    /* 通过获取用户信息判断是否登录 */
    @RequestMapping("isLogin")
    public String isLogin(HttpServletRequest request){
        String username = UserTokenUtil.getUserAccount(request);
        if (username == null){
            return "";
        }
        return username;
    }

    /* 退出登录 (清除token中的数据) */
    @RequestMapping("exit")
    public void exit(HttpServletResponse response, HttpServletRequest request){
        UserTokenUtil.deleteUserToken(response,request,stringRedisTemplate);
    }

}

